﻿'   fTray Extended console class
'   Copyright (c) 2010 Marvin Westmaas ( MtM / Marvin_The_Martian )
'
'   This program is free software: you can redistribute it and/or modify
'   it under the terms of the GNU General Public License as published by
'   the Free Software Foundation, either version 3 of the License, or
'   (at your option) any later version.
'
'   This program is distributed in the hope that it will be useful,
'   but WITHOUT ANY WARRANTY; without even the implied warranty of
'   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'   GNU General Public License for more details.
'
'   You should have received a copy of the GNU General Public License
'   along with this program.  If not, see <http://www.gnu.org/licenses/>.
Imports System.IO
Imports System.Diagnostics

Public Class frmLOG
#Region "Declares"
    Private WithEvents QueueEvent As clsQueue
    Private tMinInterval As Long
    Private WithEvents tInterval As New Timer
    Private WithEvents tCheckB As New ToolStripCheckBox
    'Private WithEvents ClientControl As clsClientControl = modMAIN.ClientControl
#End Region
#Region "Form events"
    Public Sub New()
        InitializeComponent()
    End Sub
    Private Sub nIcon_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles nIcon.MouseClick
        Try
            If e.Button = Windows.Forms.MouseButtons.Left Then
                If Me.Visible Then
                    Me.Hide()
                Else
                    Me.Show()
                    Me.TopMost = True
                End If
            End If
        Catch ex As Exception

        End Try
    End Sub
    Private Sub nIcon_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles nIcon.MouseUp
        Try
            nIcon.ContextMenuStrip = Nothing
            If e.Button = MouseButtons.Right Then
                For Each oForm As Form In Application.OpenForms
                    If oForm.Text = ClientEXE & " -configonly" Then
                        oForm.Activate()
                        Exit Sub
                    End If
                Next
                nIcon.ContextMenuStrip = fLog.cMenu
            End If
        Catch ex As Exception

        End Try
    End Sub
    Private Sub cMenu_Opening(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles cMenu.Opening
        Try
            If ClientControl.ConsoleStatus = clsClientControl.eStatus.stopped Then
                StopToolStripMenuItem.Enabled = False
                ShowHideToolStripMenuItem.Enabled = True
                StartToolStripMenuItem.Enabled = True
            ElseIf ClientControl.ConsoleStatus = clsClientControl.eStatus.active Then
                StartToolStripMenuItem.Enabled = False
                StopToolStripMenuItem.Enabled = True
                ShowHideToolStripMenuItem.Enabled = True
            End If
        Catch ex As Exception

        End Try
    End Sub
    Private Sub StopToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopToolStripMenuItem.Click
        Try
            ClientControl.StopClient()
            'tIcon.Enabled = True
        Catch ex As Exception

        End Try
    End Sub
    Private Sub StartToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartToolStripMenuItem.Click
        Try
            ClientControl.StartClient()
            'tIcon.Enabled = True
        Catch ex As Exception

        End Try
    End Sub
    Private Sub PauseToolStripMenuItem_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            ClientControl.PauseClient()
            'tIcon.Enabled = True
        Catch ex As Exception

        End Try
    End Sub
    Private Sub ShowHideToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ShowHideToolStripMenuItem.Click
        Try
            If Me.Visible Then
                Me.Hide()
            Else
                Me.Show()
            End If

        Catch ex As Exception

        End Try
    End Sub
    Private Sub CloseFTrayToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseFTrayToolStripMenuItem.Click
        Try
            'make console visible always on exit
            If Not ClientControl.IsService And ClientControl.WindowState = clsClientControl.eWindowState.Hidden Then ClientControl.ShowConsole()
            nIcon.Visible = False
            Application.Exit()
        Catch ex As Exception

        End Try
    End Sub
    Private Sub ConfigureToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConfigureToolStripMenuItem.Click
        Try
            If ClientControl.ConfigureClient Then nIcon.ContextMenu = Nothing
        Catch ex As Exception

        End Try
    End Sub
    Private Sub OptionsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OptionsToolStripMenuItem.Click
        Try
            AboutBox.Show()
            'frmOptions.Show()
        Catch ex As Exception

        End Try
    End Sub
    Private Sub tCheckB_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles tCheckB.CheckedChanged
        Try
            If tCheckB.Checked Then
                lblEta.Text = ClientControl.Queue.Eta2
            Else
                lblEta.Text = ClientControl.Queue.Eta
            End If
        Catch ex As Exception

        End Try
    End Sub
    Private Sub frmLOG_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Try
            If e.CloseReason = CloseReason.UserClosing Then
                e.Cancel = True
                Me.Visible = False
            End If
        Catch ex As Exception

        End Try
    End Sub
    Private Sub frmLOG_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            Me.Visible = False
            ClientControl = New clsClientControl(ClientPath, ClientEXE)
            If ClientControl.IsService = False And ClientControl.ConsoleStatus = clsClientControl.eStatus.active & ClientControl.WindowState = clsClientControl.eWindowState.Visible Then
                'hide the console window
                ClientControl.HideConsole()
            End If

            AddHandler ClientControl.ConsoleExited, AddressOf ClientProcExit
            AddHandler ClientControl.ConsoleAttached, AddressOf ClientProcAttached

            ProjectInfo = New clsProjectInfo(ClientPath)
            If ProjectInfo.IsEmpty Then ProjectInfo.GetProjects()

            rtf.Parent = tsCont.ContentPanel
            rtf.Dock = DockStyle.Fill
            Dim mLen As Int32 = Int32.MaxValue
            rtf.MaxLength = mLen
            tCheckB.Text = "Change ETA style"

            tsTop.Items.Add(tCheckB)
            tsTop.Items(tsTop.Items.Count - 1).Alignment = ToolStripItemAlignment.Right

            tsCont.TopToolStripPanel.Controls.Add(tsTop)
            tsTop.AutoSize = True

            tsCont.TopToolStripPanel.Show()
            Me.Text = ClientEXE


            ClientControl.Queue.InitQueue()
            QueueEvent = ClientControl.Queue
            QueueEvent.StartWatching()

            InvokeUpdate()

        Catch ex As Exception

        End Try
    End Sub
    Private Sub tClock_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tClock.Tick
        Try
            'Clock update, should not call invoke update 

            UpdateIcon()
            Dim currentStatus As clsClientControl.eStatus = ClientControl.ConsoleStatus

            If currentStatus = clsClientControl.eStatus.active Then
                Dim doTick As New tTick(AddressOf UpdateTick)
                Me.Invoke(doTick)
            End If
            Static _sOldStatus As clsClientControl.eStatus = clsClientControl.eStatus.failure
            If currentStatus <> _sOldStatus Then
                'Needed this check to respond properly to checks for running console or not
                _sOldStatus = currentStatus
                InvokeUpdate()
            End If

            'InvokeUpdate()

        Catch ex As Exception

        End Try
    End Sub
    Private Sub cmbQslots_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmbQslots.SelectedIndexChanged
        Try
            Dim qSlot As clsQueue.Entry = ClientControl.Queue.Slot(cmbQslots.SelectedIndex)
            With qSlot
                If .Status = "1" Then
                    lblStatus.Text = "Active"
                ElseIf .Status = "0" Then
                    If .UploadStatus = "1" Then
                        lblStatus.Text = "Finished"
                    Else
                        lblStatus.Text = "Ready to upload"
                    End If
                End If
                lblUser.Text = .UserName
                lblTeam.Text = .TeamNumber
                If .PassKey <> "" Then
                    lblPK.Text = "Yes"
                Else
                    lblPK.Text = "No"
                End If
                lblBT.Text = .TimeData.BeginTime
                If .TimeData.EndTime = #1/1/2000# Then
                    If ClientControl.ConsoleStatus = clsClientControl.eStatus.active Then
                        lblET.Text = ClientControl.Queue.Eta
                        lblET.ForeColor = Color.Blue
                    Else
                        lblET.Text = "Unkown"
                        lblET.ForeColor = Control.DefaultForeColor
                    End If
                Else
                    lblET.Text = .TimeData.EndTime
                    lblET.ForeColor = Control.DefaultForeColor
                End If
                'If timedate is filled, might be nice to add effective ppd based on total completion time to the upload field 
                'when the queueevents are working properly this will also be added to statistics
                lblUS.Text = .UploadStatus
                lblCore.Text = "FahCore_" & .CoreNumber
                lblUF.Text = .UploadFailures
                If .BenchMark = "0" Then
                    lblBident.Text = "Flops"
                    lblBench.Text = .Flops
                Else
                    lblBench.Text = .BenchMark
                    lblBident.Text = "Benchmark"
                End If
                lblIssued.Text = .Issued
                If ProjectInfo.KnownProject(.Project.Project) Then
                    lblPreff.Text = .Due.AddDays(ProjectInfo.Project(.Project.Project).PreferredDays.Replace(".", ","))
                    lblExpires.Text = .Due.AddDays(ProjectInfo.Project(.Project.Project).FinalDeadline.Replace(".", ","))
                Else
                    lblPreff.Text = "Unkown"
                    lblExpires.Text = "Unkown"
                End If
            End With
        Catch ex As Exception

        End Try
    End Sub
    Private Sub cmdStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStop.Click
        Try
            ClientControl.StopClient()
        Catch ex As Exception

        End Try
    End Sub
    Private Sub cmdStart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdStart.Click
        Try
            ClientControl.StartClient()
        Catch ex As Exception

        End Try
    End Sub
    Private Sub cmdConfigure_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdConfigure.Click
        Try
            If ClientControl.ConfigureClient Then
                nIcon.ContextMenu = Nothing
                Me.Enabled = False
            End If

        Catch ex As Exception

        End Try
    End Sub
    Private Sub lblDescription_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lblDescription.LinkClicked
        Try
            If Not lblDescription.Text = "overusingIPswillbebanned" Then
                Process.Start(lblDescription.Text)
            End If
        Catch ex As Exception

        End Try
    End Sub
#End Region
#Region "Updating"
    Public Delegate Sub tTick()
    Public Delegate Sub DoUpdateP()
    Public Enum eIconState
        Active
        Paused
        Stopped
        LogWarning
        Log
        _skip
    End Enum
    Public Sub UpdateTick()
        Try
            If tCheckB.Checked Then
                lblEta.Text = ClientControl.Queue.Eta2
                If ProjectInfo.KnownProject(ClientControl.Queue.ActiveSlot.Project.Project) Then
                    If ClientControl.Queue.Eta > ClientControl.Queue.ActiveSlot.Issued.AddDays(ProjectInfo.Project(ClientControl.Queue.ActiveSlot.Project.Project).FinalDeadline.Replace(".", ",")) Then
                        lblEta.ForeColor = Color.Red
                    ElseIf ClientControl.Queue.Eta > ClientControl.Queue.ActiveSlot.Issued.AddDays(ProjectInfo.Project(ClientControl.Queue.ActiveSlot.Project.Project).PreferredDays.Replace(".", ",")) Then
                        lblEta.ForeColor = Color.Blue
                    Else
                        If lblEta.ForeColor <> Control.DefaultForeColor Then lblEta.ForeColor = Control.DefaultForeColor
                    End If
                Else
                    lblEta.ForeColor = Control.DefaultForeColor
                End If
            Else
                If lblEta.ForeColor <> Control.DefaultForeColor Then lblEta.ForeColor = Control.DefaultForeColor
            End If
        Catch ex As Exception

        End Try
    End Sub
    Public Function UpdateIcon(Optional ByVal IconState As eIconState = eIconState._skip)
        Try
            If IconState = eIconState._skip Then
                Select Case ClientControl.ConsoleStatus
                    Case Is = clsClientControl.eStatus.active
                        nIcon.Text = "Progress: " & ClientControl.Queue.Progress & "%" & vbNewLine & "Eta: " & ClientControl.Queue.Eta2
                        nIcon.Icon = My.Resources.fTray
                    Case Is = clsClientControl.eStatus.failure
                        nIcon.Icon = My.Resources.fTray_Warning
                        nIcon.Text = "Warning: "
                    Case Is = clsClientControl.eStatus.paused
                        nIcon.Icon = My.Resources.fTray_stop
                        nIcon.Text = "Stopped!"
                    Case Is = clsClientControl.eStatus.stopped
                        nIcon.Icon = My.Resources.fTray_Start
                        nIcon.Text = "Stopped"
                End Select
            Else
                Select Case IconState
                    Case Is = eIconState.Active
                        nIcon.Icon = My.Resources.fTray
                        nIcon.Text = "Progress: " & ClientControl.Queue.Progress & "%" & vbNewLine & "Eta: " & ClientControl.Queue.Eta2
                    Case Is = eIconState.LogWarning
                        nIcon.Icon = My.Resources.fTray_Warning
                    Case Is = eIconState.Stopped
                        nIcon.Icon = My.Resources.fTray_Start
                End Select
            End If
            'nIcon.Icon = My.Resources.Resource1.fTray
            Return True
        Catch ex As Exception
            Return False
        Finally
            nIcon.Visible = True
        End Try
    End Function
    Public Sub InvokeUpdate()
        Try
            Dim Update As New DoUpdateP(AddressOf UpdateProgress)
            Me.Invoke(Update)
        Catch ex As Exception

        End Try
    End Sub
    Public Shadows Sub UpdateProgress()
        Try
            'Check control states
            Dim _IsClientService As Boolean = ClientControl.IsService
            Dim _ClientSerStatus As ServiceProcess.ServiceControllerStatus = ClientControl.ServiceStatus
            Dim _ClientControlStatus As clsClientControl.eStatus = ClientControl.ConsoleStatus

            If _IsClientService Then
                If _ClientSerStatus = ServiceProcess.ServiceControllerStatus.Running Or _
                    _ClientSerStatus = ServiceProcess.ServiceControllerStatus.StartPending Then
                    cmdStop.Enabled = True
                    cmdStart.Enabled = False
                    cmdStop.ContextMenuStrip = Nothing
                ElseIf _ClientSerStatus = ServiceProcess.ServiceControllerStatus.Stopped Or _
                    _ClientSerStatus = ServiceProcess.ServiceControllerStatus.StopPending Then
                    cmdStop.Enabled = False
                    cmdStart.Enabled = True
                    cmdStop.ContextMenuStrip = Nothing
                End If
            Else
                If _ClientControlStatus = clsClientControl.eStatus.active Then
                    cmdStart.Enabled = False
                    cmdStop.Enabled = True
                    cmdStop.ContextMenuStrip = cmStop
                Else
                    cmdStop.Enabled = False
                    cmdStart.Enabled = True
                    cmdStop.ContextMenuStrip = Nothing
                End If
            End If
            'set new frame info
            If _ClientControlStatus = clsClientControl.eStatus.active Then
                pBar.Value = ClientControl.Queue.Progress
                pBar.ToolTipText = pBar.Value.ToString
                lblFrameTime.Text = ClientControl.Queue.tsFrame.ToString
                lblProject.Text = ClientControl.Queue.ActiveSlot.PRCG
                If tCheckB.Checked Then
                    lblEta.Text = ClientControl.Queue.Eta2
                Else
                    lblEta.Text = ClientControl.Queue.Eta
                End If
                tCheckB.Enabled = True
                If cmbQslots.SelectedIndex = ClientControl.Queue.Current Then
                    lblET.Text = ClientControl.Queue.Eta
                    lblET.ForeColor = Color.Blue
                End If
            Else
                pBar.Value = 0
                pBar.ToolTipText = pBar.Value.ToString
                lblFrameTime.Text = "-stopped-"
                lblProject.Text = ClientControl.Queue.ActiveSlot.PRCG
                lblEta.Text = "-unknown-"
                tCheckB.Enabled = False
                If cmbQslots.SelectedIndex = ClientControl.Queue.Current Then
                    lblET.Text = "-unknown-"
                    lblET.ForeColor = Control.DefaultForeColor
                End If
            End If
            'fill queue info
            With ClientControl.Queue
                lblQVersion.Text = .Version
                lblPerfFraction.Text = .PerformanceFraction & " (" & .PerformanceFractionUnits & ")"
                lblDR.Text = .DownloadRate & " (" & .DownloadRateUnits & ")"
                lblUR.Text = .UploadRate & " (" & .UploadRateUnits & ")"
                lblTUF.Text = .TotalUploadFailures.ToString
                'Check number of entries in cmbQueueslots
                If cmbQslots.Items.Count > 0 Then
                    'For changing queue content, use queueevents ( project end/ project start -> needs fixing! )
                    'quicker fix.. compare content and update if needed
                    Dim bQueddiff As Boolean = False
                    For xInt As Short = 0 To 9
                        Dim qSlot As clsQueue.Entry = .Slot(xInt)
                        If cmbQslots.Items(xInt).ToString <> xInt.ToString & " " & qSlot.PRCG Then
                            bQueddiff = True
                            Exit For
                        End If
                    Next
                    If bQueddiff Then
                        cmbQslots.Items.Clear()
                        GoTo DoAdd
                    End If
                Else
DoAdd:
                    'Add items from queue  
                    For xInt As Short = 0 To 9
                        Dim qSlot As clsQueue.Entry = .Slot(xInt)
                        cmbQslots.Items.Add(xInt.ToString & " " & qSlot.PRCG)
                    Next
                    cmbQslots.Text = cmbQslots.Items(.Current)
                End If
            End With
            'fill wu info
            If ProjectInfo.KnownProject(ClientControl.Queue.ActiveSlot.Project.Project) Then
                With ProjectInfo.Project(ClientControl.Queue.ActiveSlot.Project.Project)
                    lblWuName.Text = .WUName
                    If ClientControl.Queue.CoreVersion <> "" Then
                        lblWUCORE.Text = ClientControl.Queue.CoreVersion & " " & .Code
                    Else
                        lblWUCORE.Text = .Code
                    End If
                    lblWUmax.Text = .FinalDeadline
                    lblWUPref.Text = .PreferredDays
                    lblAtoms.Text = .NumberOfAtoms
                    lblCredit.Text = .Credit
                    lblDescription.Text = .Description 'mixed up
                    lblServer.Text = .ServerIP
                    lblKfactor.Text = .kFactor
                End With
            Else
                lblWUCORE.Text = "-"
                lblWUmax.Text = "-"
                lblWUPref.Text = "-"
                lblAtoms.Text = "-"
                lblCredit.Text = "-"
                lblDescription.Text = "-"
                lblServer.Text = "-"
                lblKfactor.Text = "-"
                lblWuName.Text = "-"
            End If
            'Put ppd in caption - ppd calc is messed up ( worked before, in one of my project files.. but which one lmao 
            If _ClientControlStatus = clsClientControl.eStatus.active Then
                Me.Text = ClientEXE & " Eff. ppd: " & ClientControl.Queue.PPD_Effective & " Last TPF ppd:  " & ClientControl.Queue.PPD_LastFrame
            Else
                Me.Text = ClientEXE
            End If
            'update rtf log
            Dim lFile As String = ClientPath & "\fahlog.txt"
            If Not My.Computer.FileSystem.FileExists(lFile) Then Exit Sub
            Dim fStream As FileStream = New FileStream(lFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
            Dim sRead As New StreamReader(fStream)
            If sRead.EndOfStream Then Exit Sub
            Dim rtNew As New RichTextBox
            Dim strRead As String = ""
            rtNew.MaxLength = Int32.MaxValue
            strRead = sRead.ReadToEnd
            strRead = strRead.TrimEnd([vbNewLine], [vbCr], [vbCrLf])
            strRead = Mid(strRead, 1, strRead.Length - 2)
            rtNew.Text = strRead
            fStream.Close()
            sRead = Nothing
            fStream = Nothing
            strRead = Nothing
            'get diffrence
            If rtNew.Lines.Count <= rtf.Lines.Count Then
                rtNew.Text = Nothing
            Else
                rtf.Text = rtNew.Text
                Application.DoEvents()
                rtNew = Nothing
                GoTo Scroll
            End If
Scroll:
            rtf.SelectionStart = rtf.Text.Length
        Catch ex As Exception

        End Try
    End Sub
#Region "Process events and Queue events"
#Region "Process events"
    Private Sub ClientProcExit()
        Try
            InvokeUpdate()
        Catch ex As Exception

        End Try
    End Sub
    Private Sub ClientProcAttached()
        Try
            InvokeUpdate()
        Catch ex As Exception

        End Try
    End Sub
#End Region
#Region "QueueEvents"
    Private Sub QueueEvent_EUE(ByVal CoreStatus As clsQueue.clsCoreStatus) Handles QueueEvent.EUE
        InvokeUpdate()
    End Sub
    Private Sub QueueEvent_FailedUpload(ByVal Slot As clsQueue.Entry) Handles QueueEvent.FailedUpload
        InvokeUpdate()
    End Sub
    Private Sub QueueEvent_NewFrame(ByVal CurrentProgress As Short, ByVal FrameTime As System.TimeSpan, ByVal dtFrameEnd As Date) Handles QueueEvent.NewFrame
        InvokeUpdate()
    End Sub
    Private Sub QueueEvent_ProjectEnd(ByVal Slot As clsQueue.Entry, ByVal FrameTime As System.TimeSpan, ByVal dtFrameBegin As Date, ByVal Percentage As Short) Handles QueueEvent.ProjectEnd
        InvokeUpdate()
    End Sub
    Private Sub QueueEvent_ProjectStart(ByVal Slot As clsQueue.Entry) Handles QueueEvent.ProjectStart
        InvokeUpdate()
    End Sub
#End Region
#End Region

#End Region
#Region "Toolstrip checkbox"
    'Based on msdn sample for adding controls to a toolstrip checkbox
    Public Class ToolStripCheckBox
        Inherits ToolStripControlHost
        Public Sub New()
            MyBase.New(New CheckBox)
            CheckBoxControl.BackColor = Color.Transparent
        End Sub
        Public Sub SetText(ByVal Text As String)
            CheckBoxControl.Text = Text
        End Sub
        Private ReadOnly Property CheckBoxControl() As CheckBox
            Get
                Return CType(Control, CheckBox)
            End Get
        End Property
        'Expose the CheckBoxControl's Checked Property
        Public Property Checked() As Boolean
            Get
                Return CheckBoxControl.Checked
            End Get
            Set(ByVal value As Boolean)
                CheckBoxControl.Checked = value
            End Set
        End Property
        'Subscribe and Unsubscribe the events you wish to expose
        Protected Overrides Sub OnSubscribeControlEvents(ByVal control As System.Windows.Forms.Control)
            'Connect the base events
            MyBase.OnSubscribeControlEvents(control)
            'Cast the control to a ChckBox control
            Dim checkBoxControl As CheckBox = CType(control, CheckBox)
            'Add any events you want to expose
            AddHandler checkBoxControl.CheckedChanged, AddressOf CheckedChangedHandler
        End Sub
        Protected Overrides Sub OnUnsubscribeControlEvents(ByVal control As System.Windows.Forms.Control)
            'Disconnect the base events
            MyBase.OnUnsubscribeControlEvents(control)
            'Cast the control to a CheckBox control
            Dim checkBoxControl As CheckBox = CType(control, CheckBox)
            'Remove any events you have exposed
            RemoveHandler checkBoxControl.CheckedChanged, AddressOf CheckedChangedHandler
        End Sub
        'Declare the event
        Public Event CheckedChanged As EventHandler
        'Raise the event
        Private Sub CheckedChangedHandler(ByVal sender As Object, ByVal e As EventArgs)
            RaiseEvent CheckedChanged(Me, e)
        End Sub
    End Class
#End Region
End Class